<template>
  <div class="trajectory-list" ref="trajectoryList">
    <el-card style="min-width: 300px">
      <template #header>
        <div class="card-header">
          <span>轨迹列表</span>
          <div>
            <el-input v-model="currentCarIdOfTrajectory" style="width: 120px" />
            <el-button plain @click="renderTrajectorys">搜索</el-button>
          </div>
        </div>
      </template>
      <div class="mid">
        <span :class="+power.split('%')[0] < 10 ? 'power-color' : ''"
          >当前电量:{{ power }}</span
        >
        <span>总里程:{{ mileage }}km</span>
        <el-button
          type="success"
          plain
          disabled
          size="small"
          v-if="+power.split('%')[0] > 10"
          >电量正常</el-button
        >
        <el-button type="warning" plain disabled size="small" v-else
          >电量过低</el-button
        >
      </div>
      <template #footer>
        <div
          v-for="trajectoryObj in trajectoryObjArr"
          class="trajectoryObj-item"
          @click="showTrajectory(trajectoryObj)"
        >
          <li class="first-li">
            <span style="color: #0d8adb">{{ trajectoryObj.id }}</span>
            <div>
              <span>耗时:{{ trajectoryObj.spendTime }}分</span>
              <span>耗电:{{ trajectoryObj.spendPower }}</span>
            </div>
          </li>
          <li class="second-li">
            <span>里程:{{ trajectoryObj.mileage }}</span>
            <span>{{ trajectoryObj.date }}</span>
          </li>
        </div>
      </template>
    </el-card>
  </div>
  <!-- 播放区域 -->
  <div class="play-card" ref="playCard">
    <el-card style="max-width: 480px">
      <template #header>
        <div class="card-header">
          <span>轨迹回放</span>
          <span>{{ selectTrajectoryOfPlay.id }}</span>
        </div>
      </template>
      <div class="play-control">
        <div>
          <span>播放控制:</span>
          <div class="play-button">
            <button @click="play">播放</button>
            <button @click="pause">暂停</button>
            <button @click="cancelAnimate">停止</button>
          </div>
        </div>
        <div>
          <span>播放速度:</span>
          <el-input-number
            v-model="playSpeed"
            :min="1"
            :max="10"
            @change="updateSpeed"
          />
        </div>
        <el-progress
          :text-inside="true"
          :stroke-width="26"
          :percentage="playPercentage"
        />
      </div>
    </el-card>
  </div>
</template>

<script setup>
import { onMounted, ref, computed, watch } from "vue";
import * as turf from "@turf/turf";
import { storeToRefs } from "pinia";
import { usePostStore, useMapStore } from "@/stores";
import { getCarById, getTrajectoryById } from "@/api/api";
import mapboxgl from "mapbox-gl";
const postStore = usePostStore();
const mapStore = useMapStore();
const map = mapStore.Map;
const draw = mapStore.Draw;
const { currentCarIdOfTrajectory } = storeToRefs(postStore);
//轨迹显示区域
const trajectoryList = ref(null);
//轨迹回放显示区
const playCard = ref(null);

const power = ref("");
const mileage = ref(0);
const trajectoryObjArr = ref([]);
//选中播放的轨迹
const selectTrajectoryOfPlay = ref({ id: "" });
//播放速度
const playSpeed = ref(1);
//播放的进度
const playPercentage = ref(0);
onMounted(async () => {
  trajectoryList.value.style.top = window.innerHeight * 0.07 + "px";
  playCard.value.style.bottom = window.innerHeight * 0.07 + "px";
  renderTrajectorys();
});
const renderTrajectorys = async () => {
  //加载车辆
  const car = await getCarById(currentCarIdOfTrajectory.value);
  power.value = car.power;
  mileage.value = car.mileage;

  //获取轨迹的数据
  const targetTrajectory = await getTrajectoryById(
    currentCarIdOfTrajectory.value
  );
  const trajectorys = targetTrajectory.trajectorys;
  if (trajectorys.length) {
    trajectoryObjArr.value = [];
    trajectorys.forEach((trajectory) => {
      const distance = turf.length(turf.lineString(trajectory.coordinates), {
        units: "miles",
      });
      const trajectoryObj = {};
      trajectoryObj.id = trajectory.id;
      //耗时
      trajectoryObj.spendTime = ((distance / 15) * 60).toFixed(2);
      trajectoryObj.spendPower = (distance * 1).toFixed(2) + "%";
      trajectoryObj.mileage = distance.toFixed(2) + "km";
      trajectoryObj.date = trajectory.date;
      trajectoryObj.coordinates = trajectory.coordinates;
      trajectoryObjArr.value.push(trajectoryObj);
    });
  }
};

let startPopup;
let endPopup;
//展示轨迹
const showTrajectory = (trajectoryObj) => {
  if (startPopup) {
    startPopup.remove();
  }
  if (endPopup) {
    endPopup.remove();
  }
  const coordinates = trajectoryObj.coordinates;
  //飞到车轨迹的起点处
  map.flyTo({
    center: coordinates[0],
    duration: 1000,
    speed: 0.5,
    pitch: 30,
  });
  startPopup = new mapboxgl.Popup({
    closeOnClick: false,
  })
    .setLngLat({ lng: coordinates[0][0], lat: coordinates[0][1] })
    .setText("起点")
    .addTo(map);
  startPopup._closeButton.style.margin = 0 + "px";
  const trajectoryLine = turf.lineString(coordinates);
  //添加线图层
  map.getLayer(trajectoryObj.id + "layer") &&
    map.removeLayer(trajectoryObj.id + "layer");
  map.getSource(trajectoryObj.id + "source") &&
    map.removeSource(trajectoryObj.id + "source");
  //添加
  map.addSource(trajectoryObj.id + "source", {
    type: "geojson",
    data: trajectoryLine,
  });

  map.addLayer({
    id: trajectoryObj.id + "layer",
    source: trajectoryObj.id + "source",
    type: "line",
    paint: {
      "line-width": 10,
      "line-color": "yellow",
      "line-opacity": 0.8,
    },
  });
  selectTrajectoryOfPlay.value = trajectoryObj;
  playCard.value.style.opacity = 1;
  endPopup = new mapboxgl.Popup({
    closeOnClick: false,
  })
    .setLngLat({
      lng: coordinates[coordinates.length - 1][0],
      lat: coordinates[coordinates.length - 1][1],
    })
    .setText("终点")
    .addTo(map);
  endPopup._closeButton.style.margin = 0 + "px";
};

let isToggle = true;
let isHasPlayLayer = false;
const playData = turf.point([0, 0]);
let timer = null;
let runIcon =
  "https://s1.chu0.com/src/img/png/c5/c5cf6e9b53ab4477b1d865a6131af8db.png?imageMogr2/auto-orient/thumbnail/!129x132r/gravity/Center/crop/129x132/quality/85/%7Cwatermark/3/image/aHR0cHM6Ly9zMS5haWdlaS5jb20vd2F0ZXJtYXJrLzYwLTIucG5nP2U9MTczNTQ4ODAwMCZ0b2tlbj1QN1MyWHB6ZnoxMXZBa0FTTFRrZkhON0Z3LW9PWkJlY3FlSmF4eXBMOnpYaVVCU1Y3SmNxRUUtUTZmTkdGOHVLZ3l2bz0=/dissolve/20/gravity/NorthWest/dx/43/dy/63/ws/0.0/wst/0&e=1735488000&token=1srnZGLKZ0Aqlz6dk7yF4SkiYf4eP-YrEOdM1sob:svzOrMFOkiRaefwmKAICn6J8kHU=";
//播放
const play = () => {
  console.log(map);
  if (!isToggle) {
    isToggle = true;
  }
  //添加图层
  if (!isHasPlayLayer) {
    playData.geometry.coordinates.length = 0;
    console.log(selectTrajectoryOfPlay.value);
    playData.geometry.coordinates.push(
      ...selectTrajectoryOfPlay.value.coordinates[0]
    );
    map.addSource("play-source", {
      type: "geojson",
      data: playData,
    });
    //加载图标
    map.loadImage(runIcon, function (error, image) {
      if (error) throw error;
      if (map.hasImage("car-icon")) {
        map.removeImage("car-icon");
      }
      map.addImage("car-icon", image);
    });
    //添加图层
    map.addLayer({
      id: "play-layer",
      source: "play-source",
      type: "symbol",
      layout: {
        "icon-image": "car-icon",
        "icon-rotate": ["get", "bearing"],
        "icon-rotation-alignment": "map",
        "icon-allow-overlap": true,
        "icon-ignore-placement": true,
        "icon-size": {
          type: "interval",
          stops: [
            [0, 0],
            [6, 0],
            [7, 0.4],
          ],
        },
      },
    });
    isHasPlayLayer = true;
    //播放的进度条为0
    playPercentage.value = 0;
  }

  animate();
};

const pause = () => {
  isToggle = false;
};
let sum = 10;
let start = 0;
const animate = () => {
  if (isToggle) {
    const coordinates = selectTrajectoryOfPlay.value.coordinates;
    const line = turf.lineString(coordinates);
    const length = turf.length(line, {
      units: "kilometers",
    });
    if (start > sum) {
      map.getLayer("play-layer") && map.removeLayer("play-layer");
      map.getSource("play-source") && map.removeSource("play-source");
      map.hasImage("car-icon") && map.removeImage("car-icon");
      start = 0;
      isHasPlayLayer = false;
      playPercentage.value = 0;
      return;
    }
    start += 0.01 * playSpeed.value;
    if ((start / sum) * 100 > 100) {
      playPercentage.value = 100;
    } else {
      playPercentage.value = (start / sum) * 100;
    }
    const currentCoor = turf.along(line, length * (start / sum));
    const nextCoor = turf.along(
      line,
      length * ((start + 0.01 * playSpeed.value) / sum)
    );
    const bearing = turf.bearing(currentCoor, nextCoor);
    playData.geometry.coordinates.length = 0;
    playData.geometry.coordinates.push(...currentCoor.geometry.coordinates);
    playData.properties.bearing = bearing;
    map.getSource("play-source").setData(playData);
  }
  timer = requestAnimationFrame(animate);
};

const cancelAnimate= ()=>{
  isToggle = false;
  map.getLayer("play-layer") && map.removeLayer("play-layer");
  map.getSource("play-source") && map.removeSource("play-source");
  map.hasImage("car-icon") && map.removeImage("car-icon");
  start = 0;
  isHasPlayLayer = false;
  playPercentage.value = 0;
  if(timer){
    cancelAnimationFrame(timer);
  }
}
</script>

<style scoped>
.trajectory-list {
  position: absolute;
  left: 40px;
  z-index: 10;
}
.trajectory-list .card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.trajectory-list .card-header span {
  font-weight: 600;
  font-size: 14px;
}
.trajectory-list .mid {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
  font-size: 13px;
}
.trajectoryObj-item {
  border-bottom: 2px dashed var(--el-border-color);
}
.trajectoryObj-item:hover {
  cursor: pointer;
}
.first-li,
.second-li {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 10px;
}
.first-li {
  gap: 20px;
}
.first-li div {
  display: flex;
  justify-content: space-between;
  gap: 10px;
}
.first-li div span,
.second-li span {
  font-size: 14px;
}
.play-card {
  position: absolute;
  right: 40px;
  z-index: 10;
  opacity: 0;
}
.play-card .card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.play-card .card-header span:first-child {
  font-weight: 600;
}
.play-card .play-control div {
  display: flex;
  justify-content: flex-start;
  align-items: center;
  margin: 10px 0px;
  gap: 20px;
}
.play-card .play-control .play-button {
  display: flex;
  justify-content: space-evenly;
  gap: 20px;
}
.play-card .play-control .play-button button {
  border: none;
  background-color: white;
  color: #1d8ad3;
}
.play-card .play-control .play-button button:hover {
  cursor: pointer;
}
.power-color {
  color: red;
}
</style>
